package com.example.demo.controller;

import com.example.demo.entry.Person;
import com.example.demo.entry.PersonAttributesMapper;
import com.example.demo.service.LdapPersonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ldap.InvalidNameException;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.support.LdapNameBuilder;
import org.springframework.web.bind.annotation.*;

import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapName;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yzd
 */
@RestController
@RequestMapping("/person")
public class PersonController {

    @Autowired
    private LdapPersonService ldapOperateService;
    static final String objectClass[] = {"person", "top", "uidObject", "inetOrgPerson", "organizationalPerson"};
    @Autowired
    private LdapTemplate ldapTemplate;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 获取所有 内部人员
     */
    @RequestMapping("/listUsers")
    public List<Person> listUsers() {
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("objectClass", "Person"));
        List<Person> users = new ArrayList<>();
        try {
            users = ldapTemplate.search("", filter.encode(), new PersonAttributesMapper());
        } catch (Exception e) {
            logger.error("listUsers error :", e);
        }
        return users;
    }

    /**
     * 根据cn查询单条人员信息
     * cn必须到根目录的完整路径
     *
     * @param cn
     * @return
     */
    @RequestMapping(value = "/findOneByCn", method = RequestMethod.GET)
    public Person findOneByCn(@RequestParam(name = "cn", required = false) String cn) {
        Person byCn = new Person();
        try {
            byCn = ldapOperateService.findByCn(cn);
        } catch (Exception e) {
            logger.error("findOneByCn error  cn： {} \r\n {}", cn, e);
        }
        return byCn;
    }

    /**
     * 根据ou查询人员信息
     *
     * @param ou
     * @return
     * @throws InvalidNameException
     */
    @GetMapping("/getAllByOu")
    public List<Person> findByOu(@RequestParam(required = false) String ou) throws InvalidNameException {
        LdapName name = LdapNameBuilder.newInstance("ou=" + ou).build();
        List<Person> personList = new ArrayList<>();
        try {
            ldapTemplate.findAll(name, new SearchControls(), Person.class);
        } catch (Exception e) {
            logger.error("getAllByOu error  ou： {} \r\n {}", ou, e);
        }
        return personList;
    }

    /**
     * 根据cn查询人员信息
     *
     * @param cn
     * @return
     * @throws InvalidNameException
     */
    @GetMapping("/getAllByCn")
    public List<Person> findByCn(@RequestParam(required = false) String cn) throws InvalidNameException {
        LdapName name = LdapNameBuilder.newInstance("cn=" + cn).build();
        List<Person> userInOu = new ArrayList<>();
        try {
            userInOu = ldapTemplate.findAll(name, new SearchControls(), Person.class);
        } catch (Exception e) {
            logger.error("getAllByCn error  cn： {} \r\n {}", cn, e);
        }
        return userInOu;
    }

    /**
     * 根据uid 搜搜人员信息
     *
     * @param uid
     * @return
     */
    @GetMapping("/searchPerson")
    public Person searchPerson(@RequestParam(required = false) String uid) {
        Person user = null;
        try {
            AndFilter andFilter = new AndFilter();
            andFilter.and(new EqualsFilter("objectclass", objectClass[0]));
            andFilter.and(new EqualsFilter("uid", uid));
            List<Person> search = ldapTemplate.search("", andFilter.encode(), new PersonAttributesMapper());
            if ((search != null) && !search.isEmpty()) {
                user = search.get(0);
            }
            if (user != null) {
                logger.info("search success uid ： {}, return: {}", uid, user.toString());
            } else {
                logger.info("search is null uid ： {}", uid);
            }
        } catch (NamingException e) {
            logger.error("search error userName ： {} \r\n {}", uid, e);
        } catch (Exception e) {
            logger.error("search error userName ： {} \r\n {}", uid, e);
        }
        return user;
    }

    /**
     * 根据UID查询DN
     *
     * @param
     * @return
     */
    @GetMapping("/getDnByUid")
    public String getDnByUid(@RequestParam(required = false) String uid) {
        String dn = "";
        try {
            EqualsFilter f = new EqualsFilter("uid", uid);
            List<Object> result = ldapTemplate.search("", f.toString(), new AbstractContextMapper<Object>() {
                @Override
                protected Object doMapFromContext(DirContextOperations ctx) {
                    return ctx.getNameInNamespace();
                }
            });
            if (result.size() == 1) {
                dn = result.get(0).toString();
            }
            logger.info("getDn success key ： {}, val : {}, dn: {}", "uid", uid, dn);
        } catch (NamingException e) {
            logger.error("getDn error key ： {}, val : {} \r\n {}", "uid", uid, e);
        } catch (Exception e) {
            logger.error("getDn error key ： {}, val : {} \r\n {}", "uid", uid, e);
        }
        return dn;
    }

}
